package com.xiran.srpingboottemplateself.utils;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 带过期自动删除功能的验证码工具类
 */
@Component
public class CaptchaUtil implements ApplicationRunner {

    // 验证码存储目录（可根据实际需求修改）
    private static final String CAPTCHA_DIR = "captcha-images/";
    // 验证码字符集
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    // 验证码长度
    private static final int CODE_LENGTH = 4;
    // 图片宽度
    private static final int WIDTH = 120;
    // 图片高度
    private static final int HEIGHT = 40;
    // 干扰线数量
    private static final int LINE_COUNT = 5;
    // 验证码有效期（分钟）
    private static final int EXPIRE_MINUTES = 10;
    // 随机数生成器
    private static final Random RANDOM = new Random();
    // 日期格式化（用于生成文件名）
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    static {
        // 初始化时创建验证码目录
        File dir = new File(CAPTCHA_DIR);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 生成随机验证码字符串
     */
    public static String generateCode() {
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            char c = CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length()));
            code.append(c);
        }
        return code.toString();
    }

    /**
     * 生成验证码图片并保存到指定目录
     * @return 图片文件名（包含路径）
     */
    public static String generateAndSaveImage(String code) throws IOException {
        // 生成唯一文件名（时间戳+随机数）
        String fileName = DATE_FORMAT.format(new Date()) + "_" +
                RANDOM.nextInt(1000) + ".jpg";
        String filePath = CAPTCHA_DIR + fileName;

        // 保存图片到指定目录
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            generateImage(code, fos);
        }
        return filePath;
    }

    /**
     * 根据验证码字符串生成图片
     */
    private static void generateImage(String code, OutputStream os) throws IOException {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();

        try {
            // 设置背景色
            g.setColor(getRandomColor(200, 250));
            g.fillRect(0, 0, WIDTH, HEIGHT);

            // 设置字体
            g.setFont(new Font("Arial", Font.BOLD + Font.ITALIC, 30));

            // 绘制干扰线
            for (int i = 0; i < LINE_COUNT; i++) {
                g.setColor(getRandomColor(160, 200));
                int x1 = RANDOM.nextInt(WIDTH);
                int y1 = RANDOM.nextInt(HEIGHT);
                int x2 = RANDOM.nextInt(WIDTH);
                int y2 = RANDOM.nextInt(HEIGHT);
                g.drawLine(x1, y1, x2, y2);
            }

            // 绘制验证码字符
            for (int i = 0; i < code.length(); i++) {
                g.setColor(getRandomColor(20, 130));
                g.drawString(String.valueOf(code.charAt(i)), 25 * i + 10, 30 + RANDOM.nextInt(5));
            }

            // 绘制干扰点
            for (int i = 0; i < 30; i++) {
                g.setColor(getRandomColor(100, 200));
                int x = RANDOM.nextInt(WIDTH);
                int y = RANDOM.nextInt(HEIGHT);
                g.fillOval(x, y, 2, 2);
            }

            ImageIO.write(image, "JPEG", os);
        } finally {
            g.dispose();
        }
    }

    /**
     * 生成随机颜色
     */
    private static Color getRandomColor(int min, int max) {
        if (min > 255) min = 255;
        if (max > 255) max = 255;
        int r = min + RANDOM.nextInt(max - min);
        int g = min + RANDOM.nextInt(max - min);
        int b = min + RANDOM.nextInt(max - min);
        return new Color(r, g, b);
    }

    /**
     * 启动定时任务清理过期图片
     */
    @Override
    public void run(ApplicationArguments args) {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        // 每隔5分钟执行一次清理任务
        scheduler.scheduleAtFixedRate(this::cleanExpiredImages, 0, 5, TimeUnit.MINUTES);
    }

    /**
     * 清理过期的验证码图片
     */
    private void cleanExpiredImages() {
        File dir = new File(CAPTCHA_DIR);
        File[] files = dir.listFiles();
        if (files == null) return;

        long expireTime = System.currentTimeMillis() - EXPIRE_MINUTES * 60 * 1000;

        for (File file : files) {
            // 删除过期文件
            if (file.lastModified() < expireTime) {
                try {
                    Files.delete(file.toPath());
                    System.out.println("已删除过期验证码图片: " + file.getName());
                } catch (IOException e) {
                    System.err.println("删除验证码图片失败: " + file.getName() + ", 原因: " + e.getMessage());
                }
            }
        }
    }

    // 测试方法
    public static void main(String[] args) {
        try {
            String code = generateCode();
            System.out.println("生成的验证码: " + code);
            String filePath = generateAndSaveImage(code);
            System.out.println("验证码图片已保存至: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
